home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "global.h"
- #include "mbuf.h"
- #include "ax25.h"
- #include "timer.h"
- #include "iface.h"
- #include "lapb.h"
- #include "cmdparse.h"
- #include "session.h"
- #include "st.h" /* DG2KK */
-
- extern struct tcb;
- #define NULLTCB (struct tcb *)0
-
- #ifdef FLOW
- extern int ttyflow; /* DG2KK (output flowcontrol) */
- #endif
-
- char *ax25states[] = {
- "Disconnected",
- "Conn pending",
- "Disc pending",
- "Connected",
- "Frame Reject",
- };
-
- int domycall(),dodigipeat(),doaxstat(),dot1(),dot2(),dot3(),domaxframe(),
- doaxwindow(),dopaclen(),don2(),doaxreset(),doconok(); /* DG2KK */
-
- static struct cmds axcmds[] = {
- "conok", doconok, 0, NULLCHAR, NULLCHAR, /* DG2KK */
- "digipeat", dodigipeat, 0, NULLCHAR, NULLCHAR,
- "maxframe", domaxframe, 0, NULLCHAR, NULLCHAR,
- "mycall", domycall, 0, NULLCHAR, NULLCHAR,
- "paclen", dopaclen, 0, NULLCHAR, NULLCHAR,
- "reset", doaxreset, 2, "ax25 reset <axcb>", NULLCHAR,
- "retry", don2, 0, NULLCHAR, NULLCHAR,
- "status", doaxstat, 0, NULLCHAR, NULLCHAR,
- "t1", dot1, 0, NULLCHAR, NULLCHAR,
- "t2", dot2, 0, NULLCHAR, NULLCHAR,
- "t3", dot3, 0, NULLCHAR, NULLCHAR,
- "window", doaxwindow, 0, NULLCHAR, NULLCHAR,
- NULLCHAR, NULLFP, 0, "ax25 subcommands: digipeat maxframe mycall paclen reset retry status\n\tt1 t2 t3 window", NULLCHAR,
- };
- /* Multiplexer for top-level ax25 command */
- doax25(argc,argv)
- int argc;
- char *argv[];
- {
- return subcmd(axcmds,argc,argv);
- }
-
- static
- doaxreset(argc,argv)
- int argc;
- char *argv[];
- {
- struct ax25_cb *axp;
- extern char notval[];
- long htol();
-
- axp = (struct ax25_cb *)htol(argv[1]);
- if(!ax25val(axp)){
- printf(notval);
- return 1;
- }
- reset_ax25(axp);
- return 0;
- }
-
- /* Display AX.25 link level control blocks */
- static
- doaxstat(argc,argv)
- int argc;
- char *argv[];
- {
- register int i;
- register struct ax25_cb *axp;
- char tmp[10];
- extern char notval[];
- long htol();
-
- if(argc < 2){
- printf(" &AXB IF Snd-Q Rcv-Q Remote State\n");
- for(i=0;i<NHASH;i++){
- for(axp = ax25_cb[i];axp != NULLAX25; axp = axp->next){
- pax25(tmp,&axp->addr.dest);
- printf("%8lx %-5s%-8d%-8d%-10s%s\n",
- (long)axp,axp->interface->name,
- len_q(axp->txq),len_mbuf(axp->rxq),
- tmp,ax25states[axp->state]);
- }
- }
- return 0;
- }
- axp = (struct ax25_cb *)htol(argv[1]);
- if(!ax25val(axp)){
- printf(notval);
- return 1;
- }
- dumpstat(axp);
- return 0;
- }
- /* Dump one control block */
- static
- dumpstat(axp)
- register struct ax25_cb *axp;
- {
- char tmp[10];
- int i;
-
- if(axp == NULLAX25 || axp->interface == NULLIF)
- return;
- /* DG2KK: changed "&AXB IF..." to " &AXB IF..." (Atari has 5 digit addr. */
- printf(" &AXB IF Remote RBW V(S) V(R) Unack P Retry T1 T2 T3 State\n");
- pax25(tmp,&axp->addr.dest);
- printf("%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
- putchar(axp->rejsent ? 'R' : ' ');
- putchar(axp->remotebusy ? 'B' : ' ');
- putchar(axp->waitack ? 'W' : ' ');
- printf(" %4d %4d",axp->vs,axp->vr);
- printf(" %02d/%02d %d",axp->unack,axp->maxframe,axp->proto);
- printf(" %02d/%02d",axp->retries,axp->n2);
- if(run_timer(&axp->t1))
- printf(" %02d/%02d",axp->t1.start - axp->t1.count,
- axp->t1.start);
- else
- printf(" /%02d",axp->t1.start);
-
- if(run_timer(&axp->t2))
- printf(" %02d/%02d",axp->t2.start - axp->t2.count,
- axp->t2.start);
- else
- printf(" /%02d",axp->t2.start);
-
- if(run_timer(&axp->t3))
- printf(" %02d/%02d",axp->t3.start - axp->t3.count,
- axp->t3.start);
- else
- printf(" /%02d",axp->t3.start);
-
- printf(" %s\n",ax25states[axp->state]);
- if(axp->addr.ndigis == 0)
- return;
- printf("Digipeaters:");
- for(i=0;i<axp->addr.ndigis;i++){
- pax25(tmp,&axp->addr.digis[i]);
- printf(" %s",tmp);
- }
- printf("\n");
- }
-
- /* Display or change our AX.25 address */
- static
- domycall(argc,argv)
- int argc;
- char *argv[];
- {
- char buf[15];
-
- if(argc < 2){
- pax25(buf,&mycall);
- printf("%s\n",buf);
- return 0;
- }
- if(setcall(&mycall,argv[1]) == -1)
- return -1;
- mycall.ssid |= E;
- return 0;
- }
-
- /* Control AX.25 digipeating */
- static
- dodigipeat(argc,argv)
- int argc;
- char *argv[];
- {
- extern int digipeat;
-
- if(argc == 1) {
- printf("digipeat %s\n",digipeat ? "on" : "off");
- } else {
- if(strcmp(argv[1],"on") == 0)
- digipeat = 1;
- else
- digipeat = 0;
- }
- }
-
- /* Set retransmission timer */
- static
- dot1(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 t1init;
-
- if(argc == 1) {
- printf("T1 %d\n",t1init);
- } else {
- t1init = atoi(argv[1]);
- }
- }
-
- /* Set acknowledgement delay timer */
- static
- dot2(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 t2init;
-
- if(argc == 1) {
- printf("T2 %d\n",t2init);
- } else {
- t2init = atoi(argv[1]);
- }
- }
-
- /* Set idle timer */
- static
- dot3(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 t3init;
-
- if(argc == 1) {
- printf("T3 %d\n",t3init);
- } else {
- t3init = atoi(argv[1]);
- }
- }
-
- /* Set retry limit count */
- static
- don2(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 n2;
-
- if(argc == 1) {
- printf("Retry %d\n",n2);
- } else {
- n2 = atoi(argv[1]);
- }
- }
-
- /* Set maximum number of frames that will be allowed in flight */
- static
- domaxframe(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 maxframe;
-
- if(argc == 1) {
- printf("Maxframe %d\n",maxframe);
- } else {
- maxframe = atoi(argv[1]);
- }
- }
-
- /* Set maximum length of I-frame data field */
- static
- dopaclen(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 paclen;
-
- if(argc == 1) {
- printf("Paclen %d\n",paclen);
- } else {
- paclen = atoi(argv[1]);
- }
- }
-
- /* Set high water mark on receive queue that triggers RNR */
- static
- doaxwindow(argc,argv)
- int argc;
- char *argv[];
- {
- extern int16 axwindow;
-
- if(argc == 1) {
- printf("Axwindow %d\n",axwindow);
- } else {
- axwindow = atoi(argv[1]);
- }
- }
- /* End of ax25 subcommands */
-
- /* Initiate interactive AX.25 connect to remote station */
- doconnect(argc,argv)
- int argc;
- char *argv[];
- {
- void ax_rx(),ax_tx(),ax_state();
- int ax_parse();
- struct ax25_addr dest;
- struct ax25 addr;
- struct ax25_cb *open_ax25();
- struct interface *ifp;
- struct session *s;
- extern int16 axwindow;
- int i;
-
- for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
- if(strcmp(argv[1],ifp->name) == 0)
- break;
-
- if(ifp == NULLIF){
- printf("Interface %s unknown\n",argv[1]);
- return 1;
- }
- setcall(&dest,argv[2]);
- /* See if a session already exists */
- for(s = sessions; s < &sessions[nsessions]; s++){
- if(s->type == AX25TNC
- && addreq(&s->cb.ax25_cb->addr.dest,&dest)){
- #if ( MAC || AMIGA )
- printf("Session %lu to %s already exists\n",
- #else
- printf("Session %u to %s already exists\n",
- #endif
- s - sessions,argv[2]);
- return 1;
- }
- }
- /* Allocate a session descriptor */
- if((s = newsession()) == NULLSESSION){
- printf("Too many sessions\n");
- return 1;
- }
- if((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
- strcpy(s->name,argv[2]);
- s->type = AX25TNC;
- s->parse = ax_parse;
- current = s;
- ASSIGN(addr.source,mycall); /* DG2KK: should be changed */
- setcall(&addr.dest,argv[2]);
- for(i=3; i < argc; i++)
- setcall(&addr.digis[i-3],argv[i]);
-
- addr.ndigis = i - 3;
- s->cb.ax25_cb = open_ax25(&addr,axwindow,ax_rx,ax_tx,ax_state,ifp,(char *)s);
- go();
- return 0;
- }
-
-
- /* Display changes in AX.25 state */
- void
- ax_state(axp,old,new)
- struct ax25_cb *axp;
- int old,new;
- {
- struct session *s;
- char remote[10]; /* DG2KK */
-
- s = (struct session *)axp->user;
-
- if(current != NULLSESSION && current->type == AX25TNC && current == s){
- printf("%s\n",ax25states[new]);
-
- /* added to enable a 'bell' when state is connected */
- /* ---- DG2KK: AX25 logging ---- */
- if(new == CONNECTED) {
- printf("\007");
- pax25(remote,&axp->addr.dest);
- log(NULLTCB,"Connected to %s",remote);
- }
-
- if(new == DISCONNECTED) {
- pax25(remote,&axp->addr.dest);
- log(NULLTCB,"Disconnected from %s",remote);
- cmdmode();
- }
- /* ----- */
- fflush(stdout);
- }
- if(new == DISCONNECTED){
- axp->user = NULLCHAR;
- freesession(s);
- }
- }
- /* Handle typed characters on AX.25 connection */
- int
- ax_parse(buf,cnt)
- char *buf;
- int16 cnt;
- {
- struct mbuf *bp;
- register char *cp;
- char c;
-
- if(current == NULLSESSION || current->type != AX25TNC)
- return; /* "can't happen" */
-
- /* If recording is on, record outgoing stuff too */
- if(current->record != NULLFILE)
- fwrite(buf,1,cnt,current->record);
-
- /* Allocate buffer and start it with the PID */
- bp = alloc_mbuf(cnt+1);
- *bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
- bp->cnt++;
-
- /* Copy keyboard buffer to output, stripping line feeds */
- cp = bp->data + 1;
- while(cnt-- != 0){
- c = *buf++;
- if(c != '\n'){
- *cp++ = c;
- bp->cnt++;
- }
- }
- send_ax25(current->cb.ax25_cb,bp);
- }
-
- /* This is the default receive upcall function, used when
- * someone else connects to us.
- */
- void
- ax_incom(axp,cnt)
- register struct ax25_cb *axp;
- int16 cnt;
- {
- /* temporary hack - replace with a switch */
- mbx_incom(axp,cnt);
- return;
- }
-
- /* This function sets up an ax25 chat session.
- * (Formerly ax_incom())!
- * Handle new incoming terminal sessions
- * This is the default receive upcall function, used when
- * someone else connects to us
- */
- void
- ax_session(axp,cnt) /* DG2KK: was ax_income() */
- register struct ax25_cb *axp;
- int16 cnt;
- {
- struct session *s;
- char remote[10];
- void ax_rx(),ax_state();
-
- pax25(remote,&axp->addr.dest);
- if((s = newsession()) == NULLSESSION){
- /* Out of sessions */
- disc_ax25(axp);
- return;
- }
- s->type = AX25TNC;
- s->name = malloc((int16)strlen(remote)+1);
- s->cb.ax25_cb = axp;
- s->parse = ax_parse;
- strcpy(s->name,remote);
- axp->r_upcall = ax_rx;
- axp->s_upcall = ax_state;
- axp->user = (char *)s;
- #if ( MAC || AMIGA ) /* was: (defined(MAC) || defined(AMIGA)) DG2KK */
- printf("\007Incoming AX25 session %lu from %s\n",s - sessions,remote);
- #else
- printf("\007Incoming AX25 session %u from %s\n",s - sessions,remote);
- #endif
- fflush(stdout);
- }
-
- /* Handle incoming terminal traffic */
- void
- ax_rx(axp,cnt)
- struct ax25_cb *axp;
- int16 cnt;
- {
- register struct mbuf *bp;
- struct mbuf *recv_ax25();
- char c;
-
- /* Hold output if we're not the current session */
- if(mode != CONV_MODE || current == NULLSESSION
- || current->type != AX25TNC || current->cb.ax25_cb != axp)
- return;
-
- #ifdef FLOW
- if (ttyflow == 0) /* DG2KK */
- return;
- #endif FLOW
-
- if((bp = recv_ax25(axp,cnt)) == NULLBUF)
- return;
-
- /* Display received characters, translating CR's to CR/LF */
- while(bp != NULLBUF){
- while(bp->cnt-- != 0){
- c = *bp->data++;
- putc(c,stdout);
- if(current->record){
- fputc(c,current->record);
- if(c == '\r')
- fputc('\n',current->record);
- }
- if(c == '\r')
- putc('\n',stdout);
- }
- bp = free_mbuf(bp);
- }
- if(current->record)
- fflush(current->record);
- fflush(stdout);
- }
- /* Handle transmit upcalls. Used only for file uploading */
- void
- ax_tx(axp,cnt)
- struct ax25_cb *axp;
- int16 cnt;
- {
- register char *cp;
- struct session *s;
- register struct mbuf *bp;
- int16 size;
- int c;
-
- if((s = (struct session *)axp->user) == NULLSESSION
- || s->upload == NULLFILE)
- return;
- while(cnt != 0){
- size = min(cnt,axp->paclen+1);
- if((bp = alloc_mbuf(size)) == NULLBUF)
- break;
- cp = bp->data;
- /* Start with the PID */
- *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
- bp->cnt++;
-
- /* Now send data characters, translating between local
- * keyboard end-of-line sequences and the (unwritten)
- * AX.25 convention, which is carriage-return only
- */
- while(bp->cnt < size){
- if((c = getc(s->upload)) == EOF)
- break;
- #ifdef MSDOS
- /* MS-DOS gives cr-lf */
- if(c == '\n')
- continue;
- #endif
- #if (UNIX || MAC || AMIGA) /*(defined(UNIX) || defined(MAC) || defined(AMIGA))*/
- /* These give lf only */
- if(c == '\n')
- c = '\r';
- #endif
- *cp++ = c;
- bp->cnt++;
- }
- if(bp->cnt > 1) {
- send_ax25(axp,bp);
- } else {
- /* Empty frame, don't bother sending */
- free_p(bp);
- break;
- }
- cnt -= bp->cnt;
- }
- if(cnt != 0){
- /* Error or end-of-file */
- fclose(s->upload);
- s->upload = NULLFILE;
- free(s->ufile);
- s->ufile = NULLCHAR;
- }
- }
-
- /* Control AX.25 connects (DG2KK) */
- static
- doconok(argc,argv)
- int argc;
- char *argv[];
- {
- extern int conok;
-
- if(argc == 1) {
- printf("conok %s\n",conok ? "on" : "off");
- } else {
- if(strcmp(argv[1],"on") == 0)
- conok = 1;
- else
- conok = 0;
- }
- }
-
-